﻿module Types
open MathNet.Numerics
open MathNet.Numerics.FSharp
open MathNet.Numerics.LinearAlgebra.Double
open System

[<CustomEquality; CustomComparison>]
type DenseVectorWrapper = 
  
  struct
    //each vector is 256 length
    val DenseVector : DenseVector
    val Index       : int
    val RealNumber  : int
    new (densevector, id, number, prev_cluster, pk) = { DenseVector = densevector; Index = id ; RealNumber = number; }
  end  

  //method to map the 256 points to a 16x16 matrix
  member this.toMatrix16x16 =    
    let densematrix = new DenseMatrix(16)
    for (index,p) in this.DenseVector |> Seq.mapi(fun i p -> (i,p)) do
      let j = index / 16 
      let i = index % 16
      densematrix.[i,j] <- p
    densematrix

  static member equalsOn f x (yobj:obj) =
    match yobj with
    | :? 'T as y -> (f x = f y)
    | _ -> false
 
  static member compareOn f x (yobj: obj) = 
    match yobj with
    | :? DenseVectorWrapper as y ->
      //compare basato sulla lunghezza dei vettori
      let length (point : DenseVector) = point |> Seq.map(fun elem -> elem * elem) |> Seq.sum |> Math.Sqrt
      let x_length = length (x :> DenseVectorWrapper).DenseVector
      let y_length = length y.DenseVector
      compare x_length y_length
    | _ -> invalidArg "yobj" "cannot compare values of different types"

  static member GetDenseVector (s : DenseVectorWrapper) = s.DenseVector
  override x.Equals y = DenseVectorWrapper.equalsOn DenseVectorWrapper.GetDenseVector x y 
  interface System.IComparable with
    member x.CompareTo y = DenseVectorWrapper.compareOn DenseVectorWrapper.GetDenseVector x y
